package cn.rebelsoft.tools;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

public class e2d {
	/**
	 * Logger for this class
	 */

	private static final int MYSQL = 0;
	private static final int SQLSERVER = 1;
	private static final int ORACLE = 2;
	// 存储输出结果
	private static StringBuilder sqlString = new StringBuilder();

	public static void main(String[] args) throws Exception {
		excelToDDL(MYSQL);
	}

	private static void excelToDDL(int sqlType) throws Exception {
		sqlString.append("/*\n*此文件由e2d自动输出\n*e2d版本：v0.1\n*作者：1433508@qq.com\n*/");
		// 设定FileINputStream读取指定的Excel文件
		FileInputStream finput = new FileInputStream("t.xls");

		POIFSFileSystem fs = new POIFSFileSystem(finput);
		HSSFWorkbook wb = new HSSFWorkbook(fs);

		// 读取第一个工作表
		HSSFSheet sheet = wb.getSheetAt(0);
		finput.close();
		// 定义一行
		HSSFRow row = null;
		// 定义一个单元格
		HSSFCell cell = null;

		int i = 0;
		int y = 0;

		// 标志位，用于记录是否开始表定义和列定义
		boolean table = false;
		int tableCol = 1;
		boolean col = false;
		int colCol = 1;
		int colFlag = 0;
		String tableComment = "";

		// 读取所有储存格资料
		for (i = 0; i <= sheet.getLastRowNum(); i++) {
			// 读取一行
			row = sheet.getRow(i);
			// 将表定义标准和列定义标志都恢复为1
			tableCol = 1;
			colCol = 1;

			if (row != null) {
				for (y = 0; y < row.getLastCellNum(); y++) {
					// 读取一个单元格
					cell = row.getCell(y);
					if (cell != null) {
						// 判断储存格的格式
						switch (cell.getCellType()) {
						case HSSFCell.CELL_TYPE_NUMERIC:
							// 获取数字类型的单元格内容
							System.out.print(cell.getNumericCellValue());
							// getNumericCellValue()会回传double值，若不希望出现小数点，请自行转型为int
							break;
						case HSSFCell.CELL_TYPE_STRING:
							// 获取文本类型的单元格内容
							String value = cell.getStringCellValue();
							// System.out.println("\n========读取第" + i + "行第" + y
							// + "个单元格,值为" + value + "======");
							// 判断单元格内容
							if (value.equals("!s")) {
								// 表格定义开始
								sqlString.append("\n\n\n");
								table = true;
								// 读取下一行
								continue;
							} else if (value.equals("!e")) {
								// 表格定义结束
								// 闭合列定义
								// 输出公共列
								pringCommonCol(sqlType);
								printPrimarkKey(sqlType);
								sqlString.append("\n)");
								// 闭合表定义
								sqlString.append("ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='" + tableComment + "';");
								table = false;
								col = false;
								// 读取下一行
								continue;
							} else {
								// 普通内容单元格
								if (table) {
									// 在表定义范围内
									if (!col) {
										// 在表定义部分
										if (tableCol == 1) {
											// 输出英文表名
											printTableDDL(value, sqlType);
											tableCol++;
										} else if (tableCol == 2) {
											// 输出表注释
											tableComment = value;
											sqlString.append("\n");
											tableCol++;
											// 更改状态，进入列定义部分
											col = true;
											colFlag = 0;
										}
									} else {
										// 在列定义部分
										if (value.equals("值域")) {
											// 表头行读完，将colFlag设为1，开始读取下一行，即列定义行
											colFlag = 1;
											continue;
										} else if (colFlag >= 1 && colCol == 1) {
											// 输出列英文名
											printColName(value, sqlType);
											colCol++;
										} else if (colFlag >= 1 && colCol == 2) {
											// 输出类型
											printColType(value, sqlType);
											colCol++;
										} else if (colFlag >= 1 && colCol == 3) {
											// 输出可否为空
											printColNullable(value, sqlType);
											colCol++;
										} else if (colFlag >= 1 && colCol == 4) {
											// 输出备注
											printColComment(value, sqlType);
											sqlString.append("\n");
											colCol++;
										}

									}
								} else {
									// 不在表定义范围内，读取下一行
									continue;
								}

							}
							break;
						case HSSFCell.CELL_TYPE_FORMULA:
							System.out.print(cell.getNumericCellValue());
							// 读出公式储存格的计算结果
							// 若要读出公式，可用cell.getCellFormula()
							break;
						default:
							System.out.println("");
							break;
						}
					}
				}
			}
		}
		saveSqlFile();
	}

	/**
	 * 输出公共列
	 */
	private static void pringCommonCol(int sqlType) {
		switch (sqlType) {
		case MYSQL:
			sqlString.append("\n");
			sqlString.append("`beizhu`  varchar(3000)  NULL  COMMENT  '备注',\n");
			sqlString.append("`v1`  varchar (64)  NULL  COMMENT  'v1',\n");
			sqlString.append("`v2`  varchar (64)  NULL  COMMENT  'v2',\n");
			sqlString.append("`v3`  varchar (64)  NULL  COMMENT  'v3',\n");
			sqlString.append("`v4`  varchar (64)  NULL  COMMENT  'v4',\n");
			sqlString.append("`v5`  varchar (64)  NULL  COMMENT  'v5',\n");
			sqlString.append("`i1`  int(11)  NULL  COMMENT  'i1',\n");
			sqlString.append("`i2`  int(11)  NULL  COMMENT  'i2',\n");
			sqlString.append("`i3`  int(11)  NULL  COMMENT  'i3',\n");
			sqlString.append("`d1`  datetime  NULL  COMMENT  'd1',\n");
			sqlString.append("`d2`  datetime  NULL  COMMENT  'd2',\n");
			sqlString.append("`m1`  decimal(10,2)  NULL  COMMENT  'm1',\n");
			sqlString.append("`m2`  decimal(10,2)  NULL  COMMENT  'm2',\n");
			sqlString.append("\n");
			sqlString.append("`create_date`  datetime  NULL  COMMENT  '创建时间',\n");
			sqlString.append("`create_by`  varchar (50)  NULL  COMMENT  '创建人ID',\n");
			sqlString.append("`create_name`  varchar (50)  NULL  COMMENT  '创建人',\n");
			sqlString.append("`update_date`  datetime  NULL  COMMENT  '最后修改时间',\n");
			sqlString.append("`update_by`  varchar (50)  NULL  COMMENT  '最后修改人ID',\n");
			sqlString.append("`update_name`  varchar (50)  NULL  COMMENT  '最后修改人',\n");
			sqlString.append("`process_id`  varchar (64)  NULL  COMMENT  '流程号',\n");
			sqlString.append("`process_stage`  varchar (64)  NULL  COMMENT  '流程阶段',\n");
			sqlString.append("`task_id`  varchar (64)  NULL  COMMENT  '任务号',\n");
			sqlString.append("`task_assignee`  varchar (64)  NULL  COMMENT  '签收人',\n");
			break;
		case SQLSERVER:
			sqlString.append("尚不支持Sql Server数据库");
			break;
		case ORACLE:
			sqlString.append("尚不支持Oracle数据");
			break;
		default:
			sqlString.append("尚不支持其他的数据库");
			break;
		}
	}

	/**
	 * 输出主键和索引
	 * 
	 * @param sqlType
	 *            目标数据库类型
	 */
	private static void printPrimarkKey(int sqlType) {

		switch (sqlType) {
		case MYSQL:
			sqlString.append("\n");
			sqlString.append("PRIMARY KEY (`Id`), \n");
			sqlString.append("UNIQUE KEY `_index` (`Id`)\n");
			break;
		case SQLSERVER:
			sqlString.append("尚不支持Sql Server数据库");
			break;
		case ORACLE:
			sqlString.append("尚不支持Oracle数据");
			break;
		default:
			sqlString.append("尚不支持其他的数据库");
			break;
		}
	}

	private static void printColComment(String value, int sqlType) {
		switch (sqlType) {
		case MYSQL:
			sqlString.append(" COMMENT  '" + value + "', ");
			break;
		case SQLSERVER:
			sqlString.append("尚不支持Sql Server数据库");
			break;
		case ORACLE:
			sqlString.append("尚不支持Oracle数据");
			break;
		default:
			sqlString.append("尚不支持其他的数据库");
			break;
		}

	}

	private static void printColDefault(String value, int sqlType) {
		switch (sqlType) {
		case MYSQL:
			sqlString.append(" DEFAULT  '" + value + "' ");
			break;
		case SQLSERVER:
			sqlString.append("尚不支持Sql Server数据库");
			break;
		case ORACLE:
			sqlString.append("尚不支持Oracle数据");
			break;
		default:
			sqlString.append("尚不支持其他的数据库");
			break;
		}

	}

	private static void printColNullable(String value, int sqlType) {
		switch (sqlType) {
		case MYSQL:
			sqlString.append(" " + value + " ");
			break;
		case SQLSERVER:
			sqlString.append("尚不支持Sql Server数据库");
			break;
		case ORACLE:
			sqlString.append("尚不支持Oracle数据");
			break;
		default:
			sqlString.append("尚不支持其他的数据库");
			break;
		}

	}

	private static void printColType(String value, int sqlType) {
		switch (sqlType) {
		case MYSQL:
			sqlString.append(" " + value + " ");
			break;
		case SQLSERVER:
			sqlString.append("尚不支持Sql Server数据库");
			break;
		case ORACLE:
			sqlString.append("尚不支持Oracle数据");
			break;
		default:
			sqlString.append("尚不支持其他的数据库");
			break;
		}

	}

	private static void printColName(String value, int sqlType) {
		switch (sqlType) {
		case MYSQL:
			sqlString.append("`" + value + "` ");
			break;
		case SQLSERVER:
			sqlString.append("尚不支持Sql Server数据库");
			break;
		case ORACLE:
			sqlString.append("尚不支持Oracle数据");
			break;
		default:
			sqlString.append("尚不支持其他的数据库");
			break;
		}

	}

	private static void printTableComment(String value, int sqlType) {
		switch (sqlType) {
		case MYSQL:
			sqlString.append(" COMMENT `" + value + "` (");
			break;
		case SQLSERVER:
			sqlString.append("尚不支持Sql Server数据库");
			break;
		case ORACLE:
			sqlString.append("尚不支持Oracle数据");
			break;
		default:
			sqlString.append("尚不支持其他的数据库");
			break;
		}

	}

	private static void printTableDDL(String value, int sqlType) {
		switch (sqlType) {
		case MYSQL:
			sqlString.append("DROP TABLE IF EXISTS `" + value + "`;\n");
			sqlString.append("CREATE TABLE `" + value + "` (");
			break;
		case SQLSERVER:
			sqlString.append("尚不支持Sql Server数据库");
			break;
		case ORACLE:
			sqlString.append("尚不支持Oracle数据");
			break;
		default:
			sqlString.append("尚不支持其他的数据库");
			break;
		}
	}

	private static void saveSqlFile() {
		try {
			// 获取当前时间，作为保存的文件名
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 设置日期格式
			String now = df.format(new Date());// new Date()为获取当前系统时间
			now = now.replace("-", "");
			now = now.replace(":", "");
			now = now.replace(" ", "");

			FileOutputStream fos = new FileOutputStream("createTable_" + now + ".sql");
			Writer out = new OutputStreamWriter(fos, "UTF-8");
			out.write(sqlString.toString());
			out.close();
			fos.close();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
